<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0"
        />
        <title>二叉树知识测评</title>
        <link
            rel="stylesheet"
            href="//cdn.jsdelivr.net/npm/element-ui@2.15.14/lib/theme-chalk/index.css"
        />
        <link
            rel="stylesheet"
            href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.5.0/styles/default.min.css"
        />
        <style>
            #app {
                max-width: 800px;
                margin: 20px auto;
                padding: 20px;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            .timer {
                font-size: 1.2em;
                text-align: right;
                margin-bottom: 20px;
                color: #e74c3c;
            }
            .exam-card {
                padding: 20px;
                border-radius: 4px;
                box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
                margin-bottom: 20px;
            }
            .question {
                margin-bottom: 20px;
                font-size: 16px;
            }
            .question-title {
                font-weight: bold;
                margin-bottom: 10px;
            }
            .options {
                margin-left: 20px;
            }
            .option {
                margin: 8px 0;
            }
            .result-card {
                padding: 20px;
                border-radius: 4px;
                box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
                margin-top: 20px;
                background-color: #f8f9fa;
            }
            .result-item {
                margin-bottom: 15px;
                border-bottom: 1px solid #eee;
                padding-bottom: 15px;
            }
            .correct {
                color: #67c23a;
                font-weight: bold;
            }
            .incorrect {
                color: #f56c6c;
                font-weight: bold;
            }
            .explanation {
                margin-top: 8px;
                padding: 10px;
                background-color: #ecf5ff;
                border-radius: 4px;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <el-container>
                <el-header>
                    <h1>二叉树知识测评</h1>
                </el-header>

                <el-main>
                    <!-- 开始考试界面 -->
                    <div v-if="examState === 'start'">
                        <el-card
                            shadow="hover"
                            class="exam-card"
                        >
                            <h2>考试说明</h2>
                            <p>本试卷包含二叉树基础知识和应用相关题目，考试时长：45分钟</p>
                            <p>题型包含单选题和多选题，请认真作答</p>
                            <el-button
                                type="primary"
                                @click="startExam"
                                >开始考试</el-button
                            >
                        </el-card>
                    </div>

                    <!-- 考试进行中界面 -->
                    <div v-if="examState === 'inProgress'">
                        <div class="timer">剩余时间: {{ formatTime(remainingTime) }}</div>

                        <div
                            v-for="(question, index) in questions"
                            :key="index"
                            class="exam-card"
                        >
                            <div class="question">
                                <div class="question-title">{{ index + 1 }}. {{ question.title }}</div>
                                <div class="options">
                                    <div
                                        v-for="(option, optIndex) in question.options"
                                        :key="optIndex"
                                        class="option"
                                    >
                                        <el-checkbox
                                            v-if="question.type === 'multiple'"
                                            v-model="userAnswers[index]"
                                            :label="optIndex"
                                        >
                                            {{ String.fromCharCode(65 + optIndex) }}. {{ option }}
                                        </el-checkbox>

                                        <el-radio
                                            v-else
                                            v-model="userAnswers[index]"
                                            :label="optIndex"
                                        >
                                            {{ String.fromCharCode(65 + optIndex) }}. {{ option }}
                                        </el-radio>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <el-button
                            type="success"
                            @click="submitExam"
                            >提交试卷</el-button
                        >
                    </div>

                    <!-- 考试结果界面 -->
                    <div v-if="examState === 'finished'">
                        <el-card
                            shadow="hover"
                            class="result-card"
                        >
                            <h2>考试结果</h2>
                            <p>得分: {{ score }}/{{ totalScore }} (正确率: {{ ((score/totalScore)*100).toFixed(1) }}%)</p>
                            <p>考试次数: {{ examCount }}</p>

                            <div
                                v-for="(result, index) in results"
                                :key="index"
                                class="result-item"
                            >
                                <div>{{ index + 1 }}. {{ questions[index].title }}</div>
                                <div>
                                    您的答案:
                                    <span :class="result.isCorrect ? 'correct' : 'incorrect'"> {{ formatUserAnswer(index) }} </span>
                                </div>
                                <div>正确答案: {{ formatCorrectAnswer(index) }}</div>
                                <div class="explanation">解析: {{ questions[index].explanation }}</div>
                            </div>

                            <el-button
                                type="primary"
                                @click="restartExam"
                                >重新考试</el-button
                            >
                        </el-card>
                    </div>
                </el-main>
            </el-container>
        </div>

        <script src="//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
        <script src="//cdn.jsdelivr.net/npm/element-ui@2.15.14/lib/index.js"></script>
        <script>
            new Vue({
                el: "#app",
                data() {
                    return {
                        examState: "start", // start, inProgress, finished
                        remainingTime: 45 * 60, // 45分钟
                        timer: null,
                        examCount: 0,
                        userAnswers: {},
                        questions: [
                            {
                                id: 1,
                                type: "single",
                                title: "二叉树中每个节点最多有多少个子节点？",
                                options: ["1个", "2个", "3个", "不受限制"],
                                answer: 1,
                                explanation: "二叉树的特点是每个节点最多有2个子节点，称为左子节点和右子节点。",
                                score: 5,
                            },
                            {
                                id: 2,
                                type: "single",
                                title: "下列哪种二叉树中，除了最后一层，其余层都是满的，并且最后一层的节点都集中在左侧？",
                                options: ["满二叉树", "完全二叉树", "二叉搜索树", "平衡二叉树"],
                                answer: 1,
                                explanation: "完全二叉树的定义：除了最后一层外，所有层都是满的，且最后一层的节点都集中在左侧。",
                                score: 5,
                            },
                            {
                                id: 3,
                                type: "multiple",
                                title: "下列哪些是二叉树的遍历方法？（多选）",
                                options: ["前序遍历", "中序遍历", "后序遍历", "层序遍历"],
                                answer: [0, 1, 2, 3],
                                explanation: "二叉树的四种基本遍历方法：前序遍历、中序遍历、后序遍历和层序遍历。",
                                score: 5,
                            },
                            {
                                id: 4,
                                type: "single",
                                title: "在前序遍历中，节点的访问顺序是？",
                                options: ["根节点 → 左子树 → 右子树", "左子树 → 根节点 → 右子树", "左子树 → 右子树 → 根节点", "按层级从上到下访问"],
                                answer: 0,
                                explanation: "前序遍历的顺序是：访问根节点 → 遍历左子树 → 遍历右子树。",
                                score: 5,
                            },
                            {
                                id: 5,
                                type: "single",
                                title: "在虚拟DOM树的操作中，通常使用哪种遍历算法？",
                                options: ["深度优先遍历", "广度优先遍历", "中序遍历", "后序遍历"],
                                answer: 0,
                                explanation: "虚拟DOM树的操作通常使用深度优先遍历，因为它更自然地反映了组件的嵌套结构。",
                                score: 5,
                            },
                            {
                                id: 6,
                                type: "multiple",
                                title: "下列哪些数据结构基于二叉树？（多选）",
                                options: ["二叉堆", "AVL树", "红黑树", "哈希表"],
                                answer: [0, 1, 2],
                                explanation: "二叉堆、AVL树和红黑树都是基于二叉树的数据结构。哈希表使用哈希函数实现，不是树结构。",
                                score: 5,
                            },
                            {
                                id: 7,
                                type: "single",
                                title: "二叉搜索树中，节点值之间的关系是？",
                                options: ["左子节点值 < 根节点值 < 右子节点值", "左子节点值 > 根节点值 > 右子节点值", "左子节点值 = 根节点值 = 右子节点值", "没有固定关系"],
                                answer: 0,
                                explanation: "二叉搜索树的性质：对于任意节点，其左子树所有节点值都小于该节点值，右子树所有节点值都大于该节点值。",
                                score: 5,
                            },
                            {
                                id: 8,
                                type: "single",
                                title: "二叉树遍历的时间复杂度通常是？",
                                options: ["O(1)", "O(log n)", "O(n)", "O(n²)"],
                                answer: 2,
                                explanation: "二叉树遍历需要访问每个节点一次，因此时间复杂度为O(n)，其中n是节点数量。",
                                score: 5,
                            },
                            {
                                id: 9,
                                type: "multiple",
                                title: "下列哪些技术使用了二叉树结构？（多选）",
                                options: ["React虚拟DOM", "数据库索引", "CSS布局", "HTTP协议"],
                                answer: [0, 1],
                                explanation: "React的虚拟DOM使用树结构表示UI组件层级；数据库索引（如B树/B+树）基于平衡树结构。",
                                score: 5,
                            },
                            {
                                id: 10,
                                type: "single",
                                title: "在React中，虚拟DOM树的更新操作主要目的是？",
                                options: ["减少直接操作真实DOM的次数", "提高JavaScript执行速度", "简化CSS样式计算", "增加内存使用"],
                                answer: 0,
                                explanation: "虚拟DOM的核心优势是通过比较算法最小化对实际DOM的操作，从而提高性能。",
                                score: 5,
                            },
                        ],
                        results: [],
                        score: 0,
                    }
                },
                computed: {
                    totalScore() {
                        return this.questions.reduce((sum, q) => sum + q.score, 0)
                    },
                },
                methods: {
                    startExam() {
                        this.examState = "inProgress"
                        this.userAnswers = []
                        this.examCount = localStorage.getItem("examCount") ? parseInt(localStorage.getItem("examCount")) + 1 : 1

                        localStorage.setItem("examCount", this.examCount)

                        // 初始化答题数组
                        this.questions.forEach((q, i) => {
                            this.$set(this.userAnswers, i, q.type === "multiple" ? [] : null)
                        })

                        // 启动倒计时
                        this.timer = setInterval(() => {
                            this.remainingTime--
                            if (this.remainingTime <= 0) {
                                clearInterval(this.timer)
                                this.submitExam()
                            }
                        }, 1000)
                    },

                    submitExam() {
                        clearInterval(this.timer)
                        this.examState = "finished"
                        this.calculateScore()
                        this.saveExamResult()
                    },

                    restartExam() {
                        this.examState = "start"
                        this.remainingTime = 45 * 60
                        this.results = []
                        this.score = 0
                    },

                    formatTime(seconds) {
                        const mins = Math.floor(seconds / 60)
                        const secs = seconds % 60
                        return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`
                    },

                    calculateScore() {
                        this.results = []
                        this.score = 0

                        this.questions.forEach((q, index) => {
                            const userAnswer = this.userAnswers[index]
                            let isCorrect = false

                            if (q.type === "multiple") {
                                // 转换为数组并排序比较
                                const sortedUser = [...userAnswer].sort().toString()
                                const sortedCorrect = [...q.answer].sort().toString()
                                isCorrect = sortedUser === sortedCorrect
                            } else {
                                isCorrect = userAnswer === q.answer
                            }

                            if (isCorrect) {
                                this.score += q.score
                            }

                            this.results.push({
                                questionId: q.id,
                                userAnswer: Array.isArray(userAnswer) ? [...userAnswer] : userAnswer,
                                correctAnswer: Array.isArray(q.answer) ? [...q.answer] : q.answer,
                                isCorrect,
                                explanation: q.explanation,
                            })
                        })
                    },

                    formatUserAnswer(index) {
                        const answer = this.userAnswers[index]
                        if (Array.isArray(answer)) {
                            return answer.map((a) => String.fromCharCode(65 + a)).join(", ")
                        }
                        return String.fromCharCode(65 + answer)
                    },

                    formatCorrectAnswer(index) {
                        const answer = this.questions[index].answer
                        if (Array.isArray(answer)) {
                            return answer.map((a) => String.fromCharCode(65 + a)).join(", ")
                        }
                        return String.fromCharCode(65 + answer)
                    },

                    saveExamResult() {
                        const history = JSON.parse(localStorage.getItem("examHistory") || "[]")
                        history.push({
                            date: new Date().toISOString(),
                            score: this.score,
                            total: this.totalScore,
                            examCount: this.examCount,
                        })
                        localStorage.setItem("examHistory", JSON.stringify(history))
                    },
                },
            })
        </script>
    </body>
</html>
